package com.tpv.app.volley.demo.util;

import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class FileUpdateRequest extends Request<String>
{
    private VolleyListener volleyListener;
    private IBodyContent body;
    private Map<String, Object> params;
    private Map<String, File> fileMap;
    private Map<String, List<File>> multiFileMap;
    
    public FileUpdateRequest(String url, Map<String, Object> params, Map<String, File> fileMap, Map<String, List<File>> multiFileMap, VolleyListener listener)
    {
        super(Method.POST, url, listener);
        this.fileMap = fileMap;
        this.multiFileMap = multiFileMap;
        this.params = params;
        this.volleyListener = listener;
        body = new BodyContentImpl();
        setRetryPolicy(new DefaultRetryPolicy(1000*60*3,DefaultRetryPolicy.DEFAULT_MAX_RETRIES,DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
    }
    
    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response)
    {
        try
        {
            String parse = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
            return Response.success(parse, HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e)
        {
            return Response.error(new VolleyError(e));
        }
    }
    
    @Override
    protected void deliverResponse(String response)
    {
        if (null != volleyListener)
        {
            volleyListener.onResponse(response);
        }
    }
    
    /*
      * 写入一个图片格式的表单
      *
       ----boundary-2018-12-21-upload-file
       Content-Disposition:form-data;name="image";filename="avatar"
       Content-Type:image/png
      (该行空一行再换行)
      图片的二进制流
      ----boundary-2018-12-21-upload-file--
      *
      *
      * */
    
    @Override
    public byte[] getBody() throws AuthFailureError
    {
        if (params.isEmpty() && fileMap.isEmpty())
        {
            return super.getBody();
        }
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        if (null != params && !params.isEmpty())
        {
            writeParamsToServer(params, bos);
        }
        if (null != fileMap && !fileMap.isEmpty())
        {
            writeOneKeyWithOneFileToServer(fileMap, bos);
        }
        if (null != multiFileMap && !multiFileMap.isEmpty())
        {
            writeOneKeyWithMultiFileToServer(multiFileMap, bos);
        }
        try
        {
            body.writeEndBoundary(bos);
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        return bos.toByteArray();
    }
    
    private void writeParamsToServer(Map<String, Object> params, ByteArrayOutputStream bos)
    {
        StringBuilder sb = new StringBuilder();
        for (String key : params.keySet())
        {
            Object value = params.get(key);
            sb.append(body.getLinesFeed());
            sb.append(body.getBodyStartBoundary());
            sb.append(body.getLinesFeed());
            sb.append(body.getContentDisposition());
            sb.append(body.getSemicolon());
            sb.append(body.getName(key));
            sb.append(body.getLinesFeed());
            sb.append(body.getLinesFeed());
            sb.append(body.getValue(value));
        }
        try
        {
            body.writeParams(bos, sb.toString());
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
    private void writeOneKeyWithOneFileToServer(Map<String, File> fileMap, ByteArrayOutputStream bos)
    {
        for (String key : fileMap.keySet())
        {
            File file = fileMap.get(key);
            writeFileToServer(key, file, bos);
        }
    }
    
    private void writeOneKeyWithMultiFileToServer(Map<String, List<File>> multiFileMap, ByteArrayOutputStream bos)
    {
        for (String key : multiFileMap.keySet())
        {
            List<File> files = multiFileMap.get(key);
            System.out.println("key=" + key + ",files.size()=" + files.size());
            for (File file : files)
            {
                writeFileToServer(key, file, bos);
            }
        }
    }
    
    private void writeFileToServer(String key, File file, ByteArrayOutputStream bos)
    {
        StringBuilder sb = new StringBuilder();
        sb.append(body.getLinesFeed());
        sb.append(body.getBodyBoundary());
        sb.append(body.getLinesFeed());
        sb.append(body.getContentDisposition());
        sb.append(body.getSemicolon());
        sb.append(body.getName(key));
        sb.append(body.getSemicolon());
        sb.append(body.getFileName(file));
        sb.append(body.getLinesFeed());
        sb.append(body.getContentType(body.getFileMimeType(file)));
        sb.append(body.getLinesFeed());
        sb.append(body.getLinesFeed());
        try
        {
            body.writeParams(bos, sb.toString());
            body.writeFile(bos, file);
        } catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    
    @Override
    public String getBodyContentType()
    {
        return body.getBodyContentType();
    }
}
